package com.kamistoat.meimeimall.common.annotation.annotationHandler;

import com.kamistoat.meimeimall.common.annotation.ClearCache;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 处理 {@link com.kamistoat.meimeimall.common.annotation.ClearCache} 注解.
 * 注意，由于 common 模块不具备主启动类，也就无法自动扫描 Component.
 * 因此需要手动在 SPI 文件中指定这些 Component 进行注入.
 * <p></p>
 * 注解属性示例: member:receiveAddress:#memberId:#isDefault.
 * <p></p>
 * 顺序-50，比全局登录拦截器 {@link com.kamistoat.meimeimall.common.interceptor.GlobalLoginInterceptor} 级别低.
 */
@Aspect
@Component
@Order(-50)
public class ClearCacheHandler {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Around(value = "@annotation(clearCache)")
    public Object innerAround(ProceedingJoinPoint proceedingJoinPoint, ClearCache clearCache) throws Throwable {
        Object proceedResult = proceedingJoinPoint.proceed();

        // 切面方法
        Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
        // 切面方法输入参数名称
        String[] paramNames = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterNames();
        // 切面方法输入参数的元类
        Class[] paramTypes = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterTypes();
        // 切面方法输入参数值
        Object[] paramValues = proceedingJoinPoint.getArgs();

        List<String> cachePrefixes = Arrays.asList(clearCache.prefixes());
        cachePrefixes.add(clearCache.prefix());

        for (String cachePrefix : cachePrefixes) {
            /**
             * 拼接缓存key
             */
            StringBuilder sb = new StringBuilder();
            assert cachePrefix.equals("");
            String[] prefixes = cachePrefix.split(":");
            for (int index = 0; index < prefixes.length; index++) {
                // 寻找到自定义部分
                if (prefixes[index].charAt(0) == '#') {
                    // 可能是单层 id，也可能是嵌套 memberEntity.id
                    String paramName = prefixes[index].substring(1);
                    // 单层
                    if(paramName.indexOf('.') == -1) {
                        for (int paramIndex = 0; paramIndex < paramNames.length; paramIndex++) {
                            if (paramNames[paramIndex].equals(paramName)) {
                                prefixes[index] = String.valueOf(paramValues[paramIndex]);
                                break;
                            }
                        }
                    }
                    // 嵌套
                    else {
                        String[] nestedParam = paramName.split("\\.");
                        String upperParamName = nestedParam[0];
                        for (int paramIndex = 0; paramIndex < paramNames.length; paramIndex++) {
                            // 首先找到输入参数中的对应变量
                            if (paramNames[paramIndex].equals(upperParamName)) {
                                // 开始向下寻找最终的getter方法
                                Object invoke = paramValues[paramIndex];
                                Class<?> aClass = paramTypes[paramIndex].newInstance().getClass();
                                for(int in = 1; in < nestedParam.length; in++){
                                    String lowerParamGetter = "get" + nestedParam[in].substring(0,1).toUpperCase() + nestedParam[in].substring(1);
                                    invoke = aClass.getMethod(lowerParamGetter).invoke(invoke);
                                    aClass = aClass.getMethod(lowerParamGetter).getReturnType();
                                }
                                prefixes[index] = String.valueOf(invoke);
                                break;
                            }
                        }
                    }
                }
                sb.append(prefixes[index]).append(":");
            }

            String prefix = sb.substring(0, sb.length() - 1);

            /**
             * 发送消息给消息队列，消息队列完成缓存的删除
             */
            rabbitTemplate.convertAndSend("third-party-event-exchange", "cache_clear_cache", prefix);
        }

        return proceedResult;
    }
}
